#ifndef TCPSERVER_H
#define TCPSERVER_H

#include <QMultiHash>
#include <QObject>
#include <QTcpServer>
#include <QThread>

#include "chatdatapack.h"
#include <QLogger>

#include <QTimer>

namespace chatserver {
class TcpClient;

enum SendDisType { Individual, Group, Broadcast };

enum SendContentType { Text, Command };

struct MesgMeta {
  QString id;
  QString sender;
  SendDisType disT;
  SendContentType contentT;
};
} // namespace chatserver

class ChatServer : public QTcpServer {
  Q_OBJECT
public:
  explicit ChatServer(int port = 9999,
                      QHostAddress addr = QHostAddress("127.0.0.1"),
                      QObject *parent = nullptr);
  virtual ~ChatServer();

private:
public slots:
  void toSendSlot(const QByteArray &data, const chatserver::MesgMeta &meta);

private slots:
  void addNewClient(const QString &id);
  void removeClient(const QString &id, const QString &group);
  void changeClientGroup(const QString &id, const QString &oldGrp,
                         const QString &newGrp);

protected:
  void incomingConnection(qintptr socketDescriptor) override;

private:
  QHash<QString, chatserver::TcpClient *> map;
  QHash<QString, QSet<QString>> groupMap;
  QLogger *logger = nullptr;
};

namespace chatserver {
class TcpClient : public QObject {
  Q_OBJECT
public:
  explicit TcpClient(QLogger *logger, qintptr dp);
  virtual ~TcpClient();

  QString gourp() { return BelongGroup; }
  QString id() { return ID; }

public slots:
  void init();
  void close();
  void sendMessage(const QByteArray &meg, const QString &sender);
  void sendCommand(const QByteArray &cmd, const QString &sender);

private slots:
  void recvRawMesg();

private:
  QLogger *logger = nullptr;
  QTimer *waitIDTimer = nullptr;
  static const int WaitIDTimeout;
  ChatDataPack pack;
  // ID 应该是QString类型，这样才能支持中文ID
  QString ID;
  qintptr socketD;
  QTcpSocket *Socket;

  QString targetID;
  bool isTarget = false;

  QString BelongGroup;

  void parse(const QByteArray &mesg);

  QString printPrefix();
  void Info(const QString &Info);
  void Warning(const QString &Info);

signals:
  void connectTo(const QString &id, chatserver::TcpClient *client);
  void disconnected(const QString &id, const QString &group);
  void sendTo(const QByteArray &data, const chatserver::MesgMeta &meta);
  void setGrp(const QString &id, const QString &oldGrp, const QString &newGrp);
};
} // namespace chatserver

#endif // TCPSERVERSHELL_H
